package com.design.patterns.structuralModel.strategy;

import com.design.patterns.structuralModel.strategy.service.context.DiscountContext;
import com.design.patterns.structuralModel.strategy.service.strategy.OverDiscountStrategy;
import com.design.patterns.structuralModel.strategy.service.strategy.PrimeDiscountStrategy;

import java.math.BigDecimal;

/**
 * 策略模式
 * 目的：定义一系列的算法，把它们一个个封装起来，并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
 */
public class StrategyMain {
    public static void main(String[] args) {
        /**
         * 我们现在模拟一个策略模式，针对付款打折
         * 将算法抽离，在使用算法的时候将算法传入到使用类中即可
         *
         * 策略模式建议找出负责用许多不同方式完成特定任务的类， 然后将其中的算法抽取到一组被称为策略的独立类中。
         * 名为上下文的原始类必须包含一个成员变量来存储对于每种策略的引用。
         * 上下文并不执行任务， 而是将工作委派给已连接的策略对象。
         * 上下文不负责选择符合任务需要的算法——客户端会将所需策略传递给上下文。
         * 实际上， 上下文并不十分了解策略，它会通过同样的通用接口与所有策略进行交互， 而该接口只需暴露一个方法来触发所选策略中封装的算法即可。
         * 因此， 上下文可独立于具体策略。
         * 这样你就可在不修改上下文代码或其他策略的情况下添加新算法或修改已有算法了。
         */

        //上下文的原始类
        DiscountContext ctx = new DiscountContext();

        // 上下文原理类中默认实现：普通会员折扣（UserDiscountStrategy）:
        BigDecimal pay1 = ctx.calculatePrice(BigDecimal.valueOf(105));
        System.out.println(pay1);

        // 当把成员变量替换为（OverDiscountStrategy）时使用满减折扣:
        ctx.setStrategy(new OverDiscountStrategy());
        BigDecimal pay2 = ctx.calculatePrice(BigDecimal.valueOf(105));
        System.out.println(pay2);

        // 当把成员变量替换为（PrimeDiscountStrategy）使用Prime会员折扣:
        ctx.setStrategy(new PrimeDiscountStrategy());
        BigDecimal pay3 = ctx.calculatePrice(BigDecimal.valueOf(105));
        System.out.println(pay3);
    }
}
